package com.lishem.leftgod.level1.class03;

/**
 * 将单向链表按某值划分成左边小、中间相等、右边大的形式
 * 【题目】
 * 给定一个单向链表的头节点head，节点的值类型是整型，再给定一个整
 * 数pivot。实现一个调整链表的函数，将链表调整为左部分都是值小于
 * pivot的节点，中间部分都是值等于pivot的节点，右部分都是值大于
 * pivot的节点。除这个要求外，对调整后的节点顺序没有更多的要求。
 * 例如：链表9->0->4->5->1，pivot=3。
 * 调整后链表可以是1->0->4->9->5，也可以是0->1->9->5->4。总之，满
 * 足左部分都是小于3的节点，中间部分都是等于3的节点（本例中这个部分为空），
 * 右部分都是大于3的节点即可。对某部分内部的节点顺序不做要求。
 */
public class Code_12_SmallerEqualBigger {

    /**
     * 用辅助数组实现
     */
    public static Node listPartition1(Node head, int pivot) {
        Node cur = head;
        int len = 0;
        while (cur != null) {
            len++;
            cur = cur.next;
        }
        cur = head;
        Node[] arr = new Node[len];
        for (int i = 0; i < len; i++) {
            arr[i] = cur;
            cur = cur.next;
        }

        int less = -1;
        int more = len;
        int index = 0;
        while (index < more) {
            if (arr[index].value < pivot) {
                swap(arr, ++less, index++);
            } else if (arr[index].value == pivot) {
                index++;
            } else {
                swap(arr, index, --more);
            }
        }
        int i = 1;
        for (; i < len; i++) {
            arr[i - 1].next = arr[i];
        }
        arr[len - 1].next = null;
        return arr[0];
    }

    public static void swap(Node[] arr, int i, int j) {
        Node tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


    /**
     * 纯链表搅
     */
    public static Node listPartition2(Node head, int pivot) {
        Node lessHead = null, less = null, equalHead = null, equal = null, moreHead = null, more = null;
        Node cur = head;
        while (cur != null) {
            if (cur.value < pivot) {
                if (lessHead == null) {
                    lessHead = cur;
                    less = cur;
                } else {
                    less.next = cur;
                    less = cur;
                }
            } else if (cur.value == pivot) {
                if (equalHead == null) {
                    equalHead = cur;
                    equal = cur;
                } else {
                    equal.next = cur;
                    equal = cur;
                }
            } else {
                if (moreHead == null) {
                    more = cur;
                    moreHead = cur;
                } else {
                    more.next = cur;
                    more = cur;
                }
            }
            head = cur.next;
            cur.next = null;
            cur = head;
        }
        if (less != null) {
            less.next = equal == null ? moreHead : equalHead;
        }
        if (equal != null) {
            equal.next = moreHead;
        }

        return lessHead != null ? lessHead : equalHead != null ? equalHead : moreHead;
    }


    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head1 = new Node(7);
        head1.next = new Node(9);
        head1.next.next = new Node(1);
        head1.next.next.next = new Node(8);
        head1.next.next.next.next = new Node(5);
        head1.next.next.next.next.next = new Node(2);
        head1.next.next.next.next.next.next = new Node(5);
        printLinkedList(head1);
//        head1 = listPartition1(head1, 4);
        head1 = listPartition2(head1, 5);
        printLinkedList(head1);

    }

}
